<h1 id="fishshell">fishshell</h1>
<p>比 bash 更好用的 shell</p>
<h2 id="安装">安装</h2>
<div class="sourceCode" id="cb1"><pre><code class="language-bash"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="co"># Ubuntu 和 Debian 的安装方法。</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="fu">sudo</span> apt-get install fish</a>
<a class="sourceLine" id="cb1-3" data-line-number="3"><span class="co"># Mac 的安装方法。</span></a>
<a class="sourceLine" id="cb1-4" data-line-number="4"><span class="ex">brew</span> install fish</a></code></pre></div>
<h2 id="启动与帮助">启动与帮助</h2>
<p>由于 <code>Fish</code> 的语法与 <code>Bash</code> 有很大差异，<code>Bash</code> 脚本一般不兼容。因此，建议不要将 <code>Fish</code> 设为默认 <code>Shell</code>，而是每次手动启动它。</p>
<div class="sourceCode" id="cb2"><pre><code class="language-bash"><a class="sourceLine" id="cb2-1" data-line-number="1"><span class="co"># 安装完成后，就可以启动 Fish。</span></a>
<a class="sourceLine" id="cb2-2" data-line-number="2">$ <span class="ex">fish</span></a>
<a class="sourceLine" id="cb2-3" data-line-number="3"><span class="co"># 使用过程中，如果需要帮助，可以输入 help 命令</span></a>
<a class="sourceLine" id="cb2-4" data-line-number="4">$ <span class="bu">help</span></a></code></pre></div>
<h2 id="彩色显示">彩色显示</h2>
<div class="sourceCode" id="cb3"><pre><code class="language-bash"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="co"># 无效命令为红色</span></a>
<a class="sourceLine" id="cb3-2" data-line-number="2">$ <span class="ex">mkd</span></a>
<a class="sourceLine" id="cb3-3" data-line-number="3"><span class="co"># 有效命令为蓝色</span></a>
<a class="sourceLine" id="cb3-4" data-line-number="4">$ <span class="fu">mkdir</span></a>
<a class="sourceLine" id="cb3-5" data-line-number="5"><span class="co"># 有效路径会有下划线。如果没有下划线，你就知道这个路径不存在。</span></a>
<a class="sourceLine" id="cb3-6" data-line-number="6">$ <span class="fu">cat</span> ~/somefi </a></code></pre></div>
<h2 id="自动建议">自动建议</h2>
<p>Fish 会自动在光标后面给出建议，表示可能的选项，颜色为灰色。如果采纳建议，可以按下 <code>→</code> 或 <code>Control + F</code> 。如果只采纳一部分，可以按下 <code>Alt + →</code>。</p>
<div class="sourceCode" id="cb4"><pre><code class="language-bash"><a class="sourceLine" id="cb4-1" data-line-number="1">$ <span class="ex">/bin/hostname</span> <span class="co"># 命令建议</span></a>
<a class="sourceLine" id="cb4-2" data-line-number="2">$ <span class="fu">grep</span> --ignore-case <span class="co"># 参数建议</span></a>
<a class="sourceLine" id="cb4-3" data-line-number="3">$ <span class="fu">ls</span> node_modules <span class="co"># 路径建议</span></a></code></pre></div>
<h2 id="自动补全">自动补全</h2>
<p>输入命令时，<code>Fish</code> 会自动显示匹配的上一条历史记录。如果没有匹配的历史记录，<code>Fish</code> 会猜测可能的结果，自动补全各种输入。比如，输入 <code>pyt</code> 再按下 <code>Tab</code> ，就会自动补全为 <code>python</code> 命令。</p>
<p><code>Fish</code> 还可以自动补全 <code>Git</code> 分支。</p>
<h2 id="脚本语法">脚本语法</h2>
<h3 id="if-语句">if 语句</h3>
<div class="sourceCode" id="cb5"><pre><code class="language-bash"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="kw">if</span> <span class="fu">grep</span> fish /etc/shells</a>
<a class="sourceLine" id="cb5-2" data-line-number="2">    <span class="bu">echo</span> Found fish</a>
<a class="sourceLine" id="cb5-3" data-line-number="3"><span class="kw">else</span> <span class="kw">if</span> <span class="fu">grep</span> bash /etc/shells</a>
<a class="sourceLine" id="cb5-4" data-line-number="4">    <span class="bu">echo</span> Found bash</a>
<a class="sourceLine" id="cb5-5" data-line-number="5"><span class="kw">else</span></a>
<a class="sourceLine" id="cb5-6" data-line-number="6">    <span class="bu">echo</span> Got nothing</a>
<a class="sourceLine" id="cb5-7" data-line-number="7"><span class="ex">end</span></a></code></pre></div>
<h3 id="switch-语句">switch 语句</h3>
<div class="sourceCode" id="cb6"><pre><code class="language-bash"><a class="sourceLine" id="cb6-1" data-line-number="1"><span class="ex">switch</span> (uname)</a>
<a class="sourceLine" id="cb6-2" data-line-number="2"><span class="kw">case</span> Linux</a>
<a class="sourceLine" id="cb6-3" data-line-number="3">    echo Hi Tux!</a>
<a class="sourceLine" id="cb6-4" data-line-number="4">case Darwin</a>
<a class="sourceLine" id="cb6-5" data-line-number="5">    echo Hi Hexley!</a>
<a class="sourceLine" id="cb6-6" data-line-number="6">case FreeBSD NetBSD DragonFly</a>
<a class="sourceLine" id="cb6-7" data-line-number="7">    echo Hi Beastie!</a>
<a class="sourceLine" id="cb6-8" data-line-number="8">case <span class="st">&#39;*&#39;</span></a>
<a class="sourceLine" id="cb6-9" data-line-number="9">    echo Hi, stranger!</a>
<a class="sourceLine" id="cb6-10" data-line-number="10">end</a></code></pre></div>
<h3 id="while-循环">while 循环</h3>
<div class="sourceCode" id="cb7"><pre><code class="language-bash"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="kw">while</span> <span class="fu">true</span></a>
<a class="sourceLine" id="cb7-2" data-line-number="2">    <span class="bu">echo</span> <span class="st">&quot;Loop forever&quot;</span></a>
<a class="sourceLine" id="cb7-3" data-line-number="3"><span class="ex">end</span></a></code></pre></div>
<h3 id="for-循环">for 循环</h3>
<div class="sourceCode" id="cb8"><pre><code class="language-bash"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="kw">for</span> <span class="fu">file</span> in *.txt</a>
<a class="sourceLine" id="cb8-2" data-line-number="2">    <span class="fu">cp</span> <span class="va">$file</span> <span class="va">$file</span>.bak</a>
<a class="sourceLine" id="cb8-3" data-line-number="3"><span class="ex">end</span></a></code></pre></div>
<h3 id="函数">函数</h3>
<p><code>Fish</code> 的函数用来封装命令，或者为现有的命令起别名。</p>
<div class="sourceCode" id="cb9"><pre><code class="language-bash"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="kw">function</span><span class="fu"> ll</span></a>
<a class="sourceLine" id="cb9-2" data-line-number="2">    <span class="fu">ls</span> -lhG <span class="va">$argv</span></a>
<a class="sourceLine" id="cb9-3" data-line-number="3"><span class="ex">end</span></a></code></pre></div>
<p>上面代码定义了一个 <code>ll</code> 函数。命令行执行这个函数以后，就可以用 <code>ll</code> 命令替代 <code>ls -lhG</code>。其中，变量 <code>$argv</code> 表示函数的参数。</p>
<div class="sourceCode" id="cb10"><pre><code class="language-bash"><a class="sourceLine" id="cb10-1" data-line-number="1"><span class="kw">function</span><span class="fu"> ls</span></a>
<a class="sourceLine" id="cb10-2" data-line-number="2">    <span class="bu">command</span> ls -hG <span class="va">$argv</span></a>
<a class="sourceLine" id="cb10-3" data-line-number="3"><span class="ex">end</span></a></code></pre></div>
<p>上面的代码重新定义 <code>ls</code> 命令。注意，函数体内的 <code>ls</code> 之前，要加上 <code>command</code>，否则会因为无限循环而报错。</p>
<h3 id="提示符">提示符</h3>
<p><code>fish_prompt</code> 函数用于定义命令行提示符（prompt）。</p>
<div class="sourceCode" id="cb11"><pre><code class="language-bash"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="kw">function</span><span class="fu"> fish_prompt</span></a>
<a class="sourceLine" id="cb11-2" data-line-number="2">  <span class="ex">set_color</span> purple</a>
<a class="sourceLine" id="cb11-3" data-line-number="3">  <span class="fu">date</span> <span class="st">&quot;+%m/%d/%y&quot;</span></a>
<a class="sourceLine" id="cb11-4" data-line-number="4">  <span class="ex">set_color</span> FF0</a>
<a class="sourceLine" id="cb11-5" data-line-number="5">  <span class="bu">echo</span> (pwd) <span class="st">&#39;&gt;&#39;</span></a>
<a class="sourceLine" id="cb11-6" data-line-number="6">  <span class="ex">set_color</span> normal</a>
<a class="sourceLine" id="cb11-7" data-line-number="7"><span class="ex">end</span></a></code></pre></div>
<p>执行上面的函数以后，你的命令行提示符就会变成下面这样。</p>
<pre><code class="language-bash">02/06/13
/home/tutorial &gt; </code></pre>
<h2 id="配置">配置</h2>
<p>Fish 的配置文件是 <code>~/.config/fish/config.fish</code>，每次 <code>Fish</code> 启动，就会自动加载这个文件。Fish 还提供 Web 界面配置该文件。</p>
<div class="sourceCode" id="cb13"><pre><code class="language-bash"><a class="sourceLine" id="cb13-1" data-line-number="1">$ <span class="ex">fish_config</span> <span class="co"># 浏览器打开 Web 界面配置</span></a></code></pre></div>
<p>Running Commands: 兼容 bash 等shell的命令执行方式<br />
Getting Help: <code>help/man cmd -&gt; browser/terminal</code><br />
Syntax Highlighting: 实时检查命令是否正确<br />
Wildcards: 支持缩写 <code>*</code> 递归 匹配<br />
Pipes and Redirections: 使用 <code>^</code> 代表 stderr<br />
Autosuggestions: 自动建议, 可以使用 <code>Ctrl-f / -&gt;</code> 来补全<br />
Tab Completions: 更强大的 tab 补全<br />
Variables: 使用 set 设置<br />
Exit Status: 使用 <code>echo $status</code> 替代 <code>$?</code><br />
Exports (Shell Variables)<br />
Lists: all variables in fish are really lists<br />
Command Substitutions: 使用 <code>(cmd)</code> 来执行命令, 而不是 反引号、<code>$()</code><br />
Combiners (And, Or, Not): 不支持使用符合来表示逻辑运算<br />
Functions：使用 <code>$argv</code> 替代 <code>$1</code><br />
Conditionals (If, Else, Switch) / Functions / Loops: 更人性化的写法(参考 py)<br />
Prompt: <code>function fish_prompt</code> 实现<br />
Startup (Where’s .bashrc?): <code>~/.config/fish/config.fish</code>，更好的方式是 autoloading-function、universal-variables<br />
Autoloading Functions: <code>~/.config/fish/functions/.</code><br />
Universal Variables：a variable whose value is shared across all instances of fish</p>
<div class="sourceCode" id="cb14"><pre><code class="language-bash"><a class="sourceLine" id="cb14-1" data-line-number="1"><span class="kw">set</span> <span class="ex">name</span> <span class="st">&#39;czl&#39;</span> <span class="co"># 设置变量，替代 name=czl</span></a>
<a class="sourceLine" id="cb14-2" data-line-number="2"><span class="bu">echo</span> <span class="va">$name</span></a>
<a class="sourceLine" id="cb14-3" data-line-number="3"><span class="bu">echo</span> <span class="va">$status</span> <span class="co"># exit status，替代 $?</span></a>
<a class="sourceLine" id="cb14-4" data-line-number="4"><span class="fu">env</span> <span class="co"># 环境变量</span></a>
<a class="sourceLine" id="cb14-5" data-line-number="5"><span class="kw">set</span> <span class="ex">-x</span> MyVariable SomeValue <span class="co"># 替代 export</span></a>
<a class="sourceLine" id="cb14-6" data-line-number="6"><span class="kw">set</span> <span class="ex">-e</span> MyVariable</a>
<a class="sourceLine" id="cb14-7" data-line-number="7"><span class="kw">set</span> <span class="ex">PATH</span> <span class="va">$PATH</span> /usr/local/bin <span class="co"># 使用 lists 记录 PATH</span></a>
<a class="sourceLine" id="cb14-8" data-line-number="8"><span class="kw">set</span> <span class="ex">-U</span> fish_user_paths /usr/local/bin <span class="va">$fish_user_paths</span> <span class="co"># 永久生效</span></a>
<a class="sourceLine" id="cb14-9" data-line-number="9"><span class="fu">touch</span> <span class="st">&quot;testing_&quot;</span>(date +%s)<span class="st">&quot;.txt&quot;</span> <span class="co"># command subtitution，替代 `date +%s`</span></a>
<a class="sourceLine" id="cb14-10" data-line-number="10"><span class="fu">cp</span> file.txt file.txt.bak<span class="kw">;</span> <span class="ex">and</span> echo <span class="st">&#39;back success&#39;</span><span class="kw">;</span> <span class="ex">or</span> echo <span class="st">&#39;back fail&#39;</span> <span class="co"># combiner</span></a>
<a class="sourceLine" id="cb14-11" data-line-number="11"><span class="ex">functions</span> <span class="co"># 列出 fish 下定义的函数</span></a></code></pre></div>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="http://fishshell.com">fish-shell官网</a></li>
</ul>
